package org.example.project.common.util;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.deser.std.StringDeserializer;
import com.fasterxml.jackson.databind.module.SimpleModule;
import org.springframework.boot.json.JsonParseException;
import org.springframework.util.StringUtils;

import java.io.IOException;

/**
 * @author wenxy
 * @date 2020/9/29
 */
public class SerializeUtils {

    public static final ObjectMapper DEFAULT_OBJECT_MAPPER = defaultObjectMapper(true);

    public static ObjectMapper defaultObjectMapper(boolean special) {
        return defaultObjectMapper(special, defaultObjectMapper());
    }

    public static ObjectMapper defaultObjectMapper(boolean special, ObjectMapper objectMapper) {
        if (special) {
            // trim
            SimpleModule module = new SimpleModule();
            module.addDeserializer(String.class, new StringDeserializer() {
                @Override
                public String deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
                    return StringUtils.trimAllWhitespace(super.deserialize(p, ctxt));
                }
            });

            objectMapper.registerModule(module);
        }
        return objectMapper;
    }

    /**
     * 为Jackson序列化提供一个ObjectMapper
     *
     * @return
     */
    public static ObjectMapper defaultObjectMapper() {
        return defaultObjectMapper(new ObjectMapper());
    }

    public static ObjectMapper defaultObjectMapper(ObjectMapper objectMapper) {
        objectMapper.findAndRegisterModules();
        // 日期序列化为数字
        objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
        // 序列化不支持的类型不报错
        objectMapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
        objectMapper.disable(SerializationFeature.FAIL_ON_SELF_REFERENCES);
        objectMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
        // 仅序列化非空字段
        objectMapper.setSerializationInclusion(JsonInclude.Include.NON_EMPTY);
        return objectMapper;
    }

    public static <T> T deserialize(String json, TypeReference<T> typeReference) {
        return deserialize(json, typeReference, DEFAULT_OBJECT_MAPPER);
    }

    public static <T> T deserialize(String json, TypeReference<T> typeReference, ObjectMapper objectMapper) {
        try {
            return objectMapper.readValue(json, typeReference);
        } catch (IOException e) {
            // 用了spring的异常类
            throw new JsonParseException(e);
        }
    }

    public static <T> String serialize(T object) {
        return serialize(object, DEFAULT_OBJECT_MAPPER);
    }

    public static <T> String serialize(T object, ObjectMapper objectMapper) {
        try {
            return objectMapper.writeValueAsString(object);
        } catch (JsonProcessingException e) {
            // 用了spring的异常类
            throw new JsonParseException(e);
        }
    }

}
